package www.reagnetbox.com.util;

import android.content.Context;


import com.kongqw.serialportlibrary.Device;
import com.kongqw.serialportlibrary.SerialPortFinder;

import java.util.ArrayList;
import java.util.List;

import www.reagnetbox.com.bean.Instruction;
import www.reagnetbox.com.callback.SimpleCallback;
import www.reagnetbox.com.others.SerialPortConst;

public class SerialPortUtils {

    private static final String TAG = "SerialPortUtils";
    private static final String DIVIDER = "20";
    private static final String EMPTY = "0000";


    public static void showAllPorts(Context context) {
        SerialPortFinder serialPortFinder = new SerialPortFinder();
        ArrayList<Device> devices = serialPortFinder.getDevices();
        if (ValidateUtil.isListValid(devices)) {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < devices.size(); i++) {
                Device device = devices.get(i);
                sb.append(i + 1).append(".").append(device.getName()).append(i == devices.size() - 1 ? "" : "\n");
            }
            XPopupUtil.showKnowPopup(context, "查找到的所有串口", sb.toString());
        } else {
            XPopupUtil.showKnowPopup(context, "查无可用串口");
        }
    }

    public static List<Device> getAllPorts() {
        SerialPortFinder serialPortFinder = new SerialPortFinder();
        return serialPortFinder.getDevices();
    }

    // 指令实体类→字节数组
    public static byte[] instructionBeanToBytes(Instruction instruction) {
        if (instruction == null) {
            return null;
        }
        StringBuilder sb = new StringBuilder();
        sb.append("7e");
        // 命令
        String command = instruction.getCommand();
        sb.append(ValidateUtil.isStringValid(command) ? command : EMPTY).append(DIVIDER);
        // 规格
        appendHexString(sb, instruction.getSpecification());
        // 库类
        Integer libType = instruction.getLibType();
        if (libType == null) {
            sb.append(EMPTY);
        } else {
            switch (libType) {
                case SerialPortConst.LIB_TYPE_NORMAL_TEMP:
                    sb.append("3031");
                    break;
                case SerialPortConst.LIB_TYPE_FREEZE_TEMP:
                    sb.append("3032");
                    break;
            }
        }
        sb.append(DIVIDER);
        // 库行
        appendHexString(sb, instruction.getLibRow());
        // 库列
        appendHexString(sb, instruction.getLibCol());
        // 托盘行
        appendHexString(sb, instruction.getPalletRow());
        // 托盘列
        appendHexString(sb, instruction.getPalletCol());
        // 料口
        Integer port = instruction.getPort();
        if (port == null) {
            sb.append(EMPTY);
        } else {
            switch (port) {
                case SerialPortConst.PORT_IN:
                    sb.append("3031");
                    break;
                case SerialPortConst.PORT_OUT_LEFT:
                    sb.append("3032");
                    break;
                case SerialPortConst.PORT_OUT_RIGHT:
                    sb.append("3033");
                    break;
            }
        }
        sb.append(DIVIDER);
        // 结果码
        sb.append(EMPTY);
        String hexString = sb.toString();
        return hexToBytes(hexString);
    }

    // 指令实体类→字符串
    public static String instructionBeanToString(Instruction instruction, boolean containResultCode) {
        if (instruction == null) {
            return null;
        }
        StringBuilder sb = new StringBuilder();
        sb.append("7e");
        // 命令
        String command = instruction.getCommand();
        sb.append(ValidateUtil.isStringValid(command) ? command : EMPTY).append(DIVIDER);
        // 规格
        appendHexString(sb, instruction.getSpecification());
        // 库类
        Integer libType = instruction.getLibType();
        if (libType == null) {
            sb.append(EMPTY);
        } else {
            switch (libType) {
                case SerialPortConst.LIB_TYPE_NORMAL_TEMP:
                    sb.append("3031");
                    break;
                case SerialPortConst.LIB_TYPE_FREEZE_TEMP:
                    sb.append("3032");
                    break;
            }
        }
        sb.append(DIVIDER);
        // 库行
        appendHexString(sb, instruction.getLibRow());
        // 库列
        appendHexString(sb, instruction.getLibCol());
        // 托盘行
        appendHexString(sb, instruction.getPalletRow());
        // 托盘列
        appendHexString(sb, instruction.getPalletCol());
        // 料口
        Integer port = instruction.getPort();
        if (port == null) {
            sb.append(EMPTY);
        } else {
            switch (port) {
                case SerialPortConst.PORT_IN:
                    sb.append("3031");
                    break;
                case SerialPortConst.PORT_OUT_LEFT:
                    sb.append("3032");
                    break;
                case SerialPortConst.PORT_OUT_RIGHT:
                    sb.append("3033");
                    break;
            }
        }
        sb.append(DIVIDER);
        if (containResultCode) {
            // 结果码
            sb.append(instruction.getResultCode());
        }
        return sb.toString();
    }


    // 指令实体类→字符串(含分隔符)(仅做调试用)
    public static String instructionBeanToStringWithDivider(Instruction instruction, boolean containResultCode, String divider) {
        if (instruction == null) {
            return null;
        }
        StringBuilder sb = new StringBuilder();
        sb.append("7e").append(divider);
        // 命令
        String command = instruction.getCommand();
        sb.append(ValidateUtil.isStringValid(command) ? command : EMPTY).append(divider);
        // 规格
        appendHexStringWithDivider(sb, instruction.getSpecification(), divider);
        // 库类
        Integer libType = instruction.getLibType();
        if (libType == null) {
            sb.append(EMPTY);
        } else {
            switch (libType) {
                case SerialPortConst.LIB_TYPE_NORMAL_TEMP:
                    sb.append("3031");
                    break;
                case SerialPortConst.LIB_TYPE_FREEZE_TEMP:
                    sb.append("3032");
                    break;
            }
        }
        sb.append(divider);
        // 库行
        appendHexStringWithDivider(sb, instruction.getLibRow(), divider);
        // 库列
        appendHexStringWithDivider(sb, instruction.getLibCol(), divider);
        // 托盘行
        appendHexStringWithDivider(sb, instruction.getPalletRow(), divider);
        // 托盘列
        appendHexStringWithDivider(sb, instruction.getPalletCol(), divider);
        // 料口
        Integer port = instruction.getPort();
        if (port == null) {
            sb.append(EMPTY);
        } else {
            switch (port) {
                case SerialPortConst.PORT_IN:
                    sb.append("3031");
                    break;
                case SerialPortConst.PORT_OUT_LEFT:
                    sb.append("3032");
                    break;
                case SerialPortConst.PORT_OUT_RIGHT:
                    sb.append("3033");
                    break;
            }
        }
        sb.append(divider);
        if (containResultCode) {
            // 结果码
            sb.append(instruction.getResultCode());
        }
        return sb.toString();
    }


    private static void appendHexString(StringBuilder sb, Integer param) {
        if (param == null) {
            sb.append(EMPTY);
        } else {
            int shi = getFigureOfNumber(param, "shi");
            int ge = getFigureOfNumber(param, "ge");
//            sb.append(Integer.toHexString(shi)).append(Integer.toHexString(ge));
            sb.append(stringToAscii(shi + "")).append(stringToAscii(ge + ""));
        }
        sb.append(DIVIDER);
    }

    private static void appendHexStringWithDivider(StringBuilder sb, Integer param, String divider) {
        if (param == null) {
            sb.append(EMPTY);
        } else {
            int shi = getFigureOfNumber(param, "shi");
            int ge = getFigureOfNumber(param, "ge");
//            sb.append(Integer.toHexString(shi)).append(Integer.toHexString(ge));
            sb.append(stringToAscii(shi + "")).append(stringToAscii(ge + ""));
        }
        sb.append(divider);
    }

    // 一长串16进制的字符串转为字节数组
    public static byte[] hexToBytes(String inHex) {
        int hexlen = inHex.length();
        byte[] result;
        if (hexlen % 2 == 1) {
            //奇数
            hexlen++;
            result = new byte[(hexlen / 2)];
            inHex = "0" + inHex;
        } else {
            //偶数
            result = new byte[(hexlen / 2)];
        }
        int j = 0;
        for (int i = 0; i < hexlen; i += 2) {
            result[j] = hexToByte(inHex.substring(i, i + 2));
            j++;
        }
        return result;
    }

    // 一个16进制字符串转为一个字节
    private static byte hexToByte(String inHex) {
        return (byte) Integer.parseInt(inHex, 16);
    }

    // 字节数组转16进制字符串
    public static String bytesToHex(byte[] bytes) {
        StringBuffer sb = new StringBuffer();
        if (bytes != null) {
            for (int i = 0; i < bytes.length; i++) {
                String hex = Integer.toHexString(bytes[i] & 0xFF);
                if (hex.length() < 2) {
                    sb.append(0);
                }
                sb.append(hex);
            }
        }
        return sb.toString();
    }

    private static int getFigureOfNumber(int number, String figureType) {
        switch (figureType) {
            case "ge":
                return number % 10;
            case "shi":
                return (number / 10) % 10;
            case "bai":
                return number / 100 % 10;
            case "qian":
                return number / 1000;
            default:
                return 0;
        }
    }

    private static String intToHexString(String figure) {
        return intToHexString(Integer.parseInt(figure));
    }

    private static String intToHexString(int figure) {
        StringBuilder ret = new StringBuilder();
        int shi = getFigureOfNumber(figure, "shi");
        int ge = getFigureOfNumber(figure, "ge");
        ret.append(stringToAscii(shi + "")).append(stringToAscii(ge + ""));
        return ret.toString();
    }

    public static String removeResultCode(String str) {
        try {
            if (str == null) {
                return null;
            }
            if (str.length() < 54) {
                return null;
            }
            String[] array = str.split("");
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < array.length; i++) {
                if (i != 51 && i != 52 && i != 53 && i != 54) {
                    sb.append(array[i]);
                }
            }
            return sb.toString();
        } catch (Exception e) {
            return null;
        }
    }


    public static String removeResultCode(byte[] bytes) {
        if (bytes == null) {
            return null;
        }
        String str = SerialPortUtils.bytesToHex(bytes);
        return removeResultCode(str);
    }

//    public static void handleReceivedBytes(Context context, byte[] receivedBytes, SimpleCallback successCallback) {
//        try {
//            // startIndex:有效指令开始的下标，即0x7e所在的下标
//            // resultCodeStartIndex:有效指令里存储结果码的开始的下标（即结果码里第一个字符(字节)所处的下标）
//            int startIndex = 0;
//            int resultCodeStartIndex = 0;
//            for (int i = 0; i < receivedBytes.length; i++) {
//                byte b = receivedBytes[i];
//                if (b == 0x7e) {
//                    startIndex = i;
//                    resultCodeStartIndex = startIndex + 25;
//                    break;
//                }
//            }
//            if (resultCodeStartIndex != 0) {
//                // 真正有效判断结果的是结果码里的第二个字符，故要resultCodeStartIndex+1
//                byte code = receivedBytes[resultCodeStartIndex + 1];
//                if (code == SerialPortConst.RESULT_CODE_SUCCESS) {// 动作执行完毕，无异常
//                    XPopupUtil.stopLoading();
//                    successCallback.fun();
//                } else if (code == SerialPortConst.RESULT_CODE_DOING) {// 正在执行
//                    XPopupUtil.startLoading(context, "设备正在执行操作,请等待...");
//                } else {
//                    XPopupUtil.stopLoading();
//                    XPopupUtil.showKnowPopup(context, "操作失败,错误码=" + code);
//                }
//            } else {
//                Log.d(TAG, "handleReceivedBytes: " + "查找不到有效指令");
//            }
//        } catch (Exception e) {
//            Log.d(TAG, "handleReceivedBytes: " + e.getMessage());
//            XPopupUtil.showKnowPopup(context, "接受数据解析异常,原因:" + e.getMessage());
//        }
//    }

    public static String getResultCode(String str) {
        String[] array = str.split("");
        StringBuilder sb = new StringBuilder();
        sb.append(array[51]).append(array[52]).append(array[53]).append(array[54]);
        return sb.toString();
    }

    public static void handleReceivedData(Context context, byte[] receivedBytes, SimpleCallback successCallback) {
        try {
            if (receivedBytes == null) {
                return;
            }
            String str = SerialPortUtils.bytesToHex(receivedBytes);
            if (str.length() < 54) {
                return;
            }
            String resultCode = getResultCode(str);
            if (resultCode.equals(SerialPortConst.RESULT_CODE_SUCCESS)) {
//                XPopupUtil.stopLoading();
                successCallback.fun();
            } else if (resultCode.equals(SerialPortConst.RESULT_CODE_DOING)) {
//                ((Activity) context).runOnUiThread(() -> XPopupUtil.startLoading(context, "设备正在执行操作,请等待..."));
            } else {
//                XPopupUtil.stopLoading();
                XPopupUtil.showKnowPopup(context, "操作失败,错误码=" + resultCode);
            }
        } catch (Exception e) {
            XPopupUtil.showKnowPopup(context, "接受数据解析异常,原因:" + e.getMessage());
        }
    }


    // 字符串转换为Ascii
    public static String stringToAscii(String value) {
        StringBuilder sb = new StringBuilder();
        char[] chars = value.toCharArray();
        for (int i = 0; i < chars.length; i++) {
            sb.append(Integer.toHexString((int) chars[i]));
        }
        return sb.toString();
    }
}
